﻿/*
Copyright (C) 2009  Tomasz Chrzanowski

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>
*/

using System;
using Com.TomCdc.ChangeDataCapture;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace CdcSchemaInstaller.Tests
{
    /// <summary>
    /// Summary description for SourceTableTest
    /// </summary>
    [TestClass]
    public class SourceTableTest
    {
        public SourceTableTest()
        {
        }

        private TestContext testContextInstance;

        private SourceTable srcTable;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        [TestInitialize]
        public void TestInitialize()
        {
            srcTable = new SourceTable("abc","abc", false);
        }

        [TestMethod]
        public void ConstructorArgsNameTest()
        {
            SourceTable srcT = new SourceTable("aaa","aaa", false);
            Assert.AreEqual("aaa", srcT.TableIdentifier);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ConstructorArgsNameNullTest()
        {
            SourceTable srcT = new SourceTable(null,null, false);
        }

        [TestMethod, ExpectedException(typeof(ArgumentException))]
        public void ConstructorArgsNameEmptyTest()
        {
            SourceTable srcT = new SourceTable("","", false);
        }

        [TestMethod]
        public void ConstructorArgsTrackedTest()
        {
            SourceTable srcT = new SourceTable("aaa","aaa", false);
            Assert.AreEqual(false, srcT.IsTracked);

            srcT = new SourceTable("aaa","aaa", true);
            Assert.AreEqual(true, srcT.IsTracked);
        }

        [TestMethod, ExpectedException(typeof(CdcSchemaInstallerException))]
        public void ConstructorDuplicatedColPosition()
        {
            srcTable.AddColumn(new SourceColumn("abc", "int", 1));
            srcTable.AddColumn(new SourceColumn("def", "int", 1));
        }

        [TestMethod]
        public void HasOrphanTriggerColumnTrueTest()
        {
            srcTable.AddOrphantColumn("abc");
            Assert.AreEqual(true, srcTable.HasOrphanTriggerColumn);
        }

        [TestMethod]
        public void HasOrphanTriggerColumnFalseTest()
        {
            Assert.AreEqual(false, srcTable.HasOrphanTriggerColumn);
        }

        [TestMethod]
        public void PrimaryKeyNoKeyTest()
        {
            Assert.IsNull(srcTable.PrimaryKey);
        }

        [TestMethod]
        public void PrimaryKeyTest()
        {
            SourceColumn tmpCol = new SourceColumn("abc", "int", 1);
            srcTable.AddColumn(tmpCol);
            srcTable.SetPrimaryKey("abc");
            Assert.AreSame(tmpCol, srcTable.PrimaryKey);
        }

        [TestMethod]
        public void AddColumnTest()
        {
            SourceColumn tmp = new SourceColumn("abc", "int", 1);
            srcTable.AddColumn(tmp);
            Assert.AreSame(tmp, srcTable.Columns["abc"]);
        }

        [TestMethod, ExpectedException(typeof(ArgumentNullException))]
        public void AddColumnNullTest()
        {
            srcTable.AddColumn(null);
        }

        [TestMethod, ExpectedException(typeof(CdcSchemaInstallerException))]
        public void AddColumnDuplicateTest()
        {
            srcTable.AddColumn(new SourceColumn("abc", "int", 1));
            srcTable.AddColumn(new SourceColumn("abc", "int", 1));
        }


        [TestMethod]
        public void AddOrphantColumnTest()
        {
            srcTable.AddOrphantColumn("abc");
            Assert.IsTrue(srcTable.IsColumnOrphan("abc"));
        }

        [TestMethod, ExpectedException(typeof(ArgumentException))]
        public void AddOrphantColumnNullTest()
        {
            srcTable.AddOrphantColumn(null);
        }

        [TestMethod, ExpectedException(typeof(ArgumentException))]
        public void AddOrphantColumnEmptyTest()
        {
            srcTable.AddOrphantColumn("");
        }

        [TestMethod, ExpectedException(typeof(CdcSchemaInstallerException))]
        public void AddOrphantColumnDuplicateTest()
        {
            srcTable.AddOrphantColumn("abc");
            srcTable.AddOrphantColumn("abc");
        }

        [TestMethod, ExpectedException(typeof(CdcSchemaInstallerException))]
        public void AddOrphantColumnSameNormalColumnTest()
        {
            srcTable.AddColumn(new SourceColumn("abc", "int", 1));
            srcTable.AddOrphantColumn("abc");
        }

        [TestMethod, ExpectedException(typeof(ArgumentException))]
        public void SetPrimaryKeyNullTest()
        {
            srcTable.SetPrimaryKey(null);
        }

        [TestMethod, ExpectedException(typeof(ArgumentException))]
        public void SetPrimaryKeyEmptyTest()
        {
            srcTable.SetPrimaryKey("");
        }

        [TestMethod, ExpectedException(typeof(CdcSchemaInstallerException))]
        public void SetPrimaryColumnNotExsistingTest()
        {
            srcTable.SetPrimaryKey("aabbcc");
        }

        [TestMethod, ExpectedException(typeof(CdcSchemaInstallerException))]
        public void SetPrimaryAlreadyDiffColSetTest()
        {
            srcTable.AddColumn(new SourceColumn("aabbcc", "int", 1));
            srcTable.AddColumn(new SourceColumn("ddeeff", "int", 2));
            
            srcTable.SetPrimaryKey("aabbcc");
            srcTable.SetPrimaryKey("ddeeff");
        }

        [TestMethod]
        public void SetPrimarySetAgainToSameTest()
        {
            srcTable.AddColumn(new SourceColumn("aabbcc", "int", 1));

            srcTable.SetPrimaryKey("aabbcc");
            srcTable.SetPrimaryKey("aabbcc");
            Assert.AreEqual(srcTable.PrimaryKey.ColumnName, "aabbcc");
        }

        [TestMethod, ExpectedException(typeof(CdcSchemaInstallerException))]
        public void GetTrackedBitmaskNothingToActivateTest()
        {
            srcTable.AddColumn(new SourceColumn("abc", "int", 1));
            string res = srcTable.GetToActivateBitmask();
        }

        [TestMethod]
        public void GetTrackedBitmaskFirstColActivate()
        {
            SourceColumn sc = new SourceColumn("abc", "int", 1);
            sc.ActivateTracking = true;
            srcTable.AddColumn(sc);

            srcTable.AddColumn(new SourceColumn("abc1", "int", 2));

            Assert.AreEqual("0x01", srcTable.GetToActivateBitmask());
        }

        [TestMethod]
        public void GetTrackedBitmaskFirst8ColActivate()
        {
            for (int i = 1; i <= 8; i++)
            {
                SourceColumn sc = new SourceColumn("abc" + i.ToString(), "int", i);
                sc.ActivateTracking = true;
                srcTable.AddColumn(sc);
            }

            Assert.AreEqual("0xFF", srcTable.GetToActivateBitmask());
        }

        [TestMethod]
        public void GetTrackedBitmaskSet1nad9ColActivate()
        {
            // 40 columns
            for (int i = 1; i <= 8*5; i++)
            {
                SourceColumn sc = new SourceColumn("abc" + i.ToString(), "int", i);
                if((i-1)%8==0) sc.ActivateTracking = true;
                srcTable.AddColumn(sc);
            }

            Assert.AreEqual("0x0101010101", srcTable.GetToActivateBitmask());
        }

        [TestMethod]
        public void GetTrackedBitmask2bitsToSecondByteColActivate()
        {
            // 40 columns
            for (int i = 1; i <= 10; i++)
            {
                SourceColumn sc = new SourceColumn("abc" + i.ToString(), "int", i);
                sc.ActivateTracking = true;
                srcTable.AddColumn(sc);
            }

            Assert.AreEqual("0xFF03", srcTable.GetToActivateBitmask());
        }

        [TestMethod, ExpectedException(typeof(CdcSchemaInstallerException))]
        public void GetToActivateColNamesNoneTest()
        {
            string[] test = srcTable.GetToActivateColNames();
        }

        [TestMethod]
        public void GetToActivateColNames1Test()
        {
            SourceColumn sc = new SourceColumn("abc", "int", 1);
            sc.ActivateTracking = true;
            srcTable.AddColumn(sc);
            Assert.AreEqual("abc", srcTable.GetToActivateColNames()[0]);
        }

        [TestMethod]
        public void GetToActivateColNames3Test()
        {
            SourceColumn sc = new SourceColumn("abc1","int", 1);
            sc.ActivateTracking = true;
            srcTable.AddColumn(sc);
            
            sc = new SourceColumn("abc2", "int", 2);
            sc.ActivateTracking = false;
            srcTable.AddColumn(sc);

            sc = new SourceColumn("abc3", "int", 3);
            sc.ActivateTracking = true;
            srcTable.AddColumn(sc);

            Assert.AreEqual("abc1", srcTable.GetToActivateColNames()[0]);
            Assert.AreEqual("abc3", srcTable.GetToActivateColNames()[1]);
        }


        [TestMethod, ExpectedException(typeof(CdcSchemaInstallerException))]
        public void GetToActivateColTypeNoneTest()
        {
            string[] test = srcTable.GetToActivateColTypes();
        }

        [TestMethod]
        public void GetToActivateColTypes1Test()
        {
            SourceColumn sc = new SourceColumn("abc", "int", 1);
            sc.ActivateTracking = true;
            srcTable.AddColumn(sc);
            Assert.AreEqual("int", srcTable.GetToActivateColTypes()[0]);
        }

        [TestMethod]
        public void GetToActivateColTypes3Test()
        {
            SourceColumn sc = new SourceColumn("abc1", "int", 1);
            sc.ActivateTracking = true;
            srcTable.AddColumn(sc);

            sc = new SourceColumn("abc2", "bigint", 2);
            sc.ActivateTracking = false;
            srcTable.AddColumn(sc);

            sc = new SourceColumn("abc3", "decimal", 3);
            sc.ActivateTracking = true;
            srcTable.AddColumn(sc);

            Assert.AreEqual("int", srcTable.GetToActivateColTypes()[0]);
            Assert.AreEqual("decimal", srcTable.GetToActivateColTypes()[1]);
        }

        [TestMethod]
        public void GetToActivateColTypes1WithLenTest()
        {
            SourceColumn sc = new SourceColumn("abc", "varchar", 1);
            sc.ActivateTracking = true;
            sc.MaxLength = 100;
            srcTable.AddColumn(sc);
            Assert.AreEqual("varchar(100)", srcTable.GetToActivateColTypes()[0]);
        }

        [TestMethod]
        public void SetAllActivate10colsTest()
        {
            for (int i = 0; i < 10; i++)
            {
                srcTable.AddColumn(new SourceColumn("abc" + i.ToString(), "int", i + 1));
            }

            srcTable.SetAllActivate(true);

            bool allactive = true;
            foreach (SourceColumn srcCol in srcTable.Columns.Values) if (!srcCol.ActivateTracking) allactive = false;
            Assert.IsTrue(allactive);
        }

        [TestMethod]
        public void SetAllActivate1disabledTest()
        {
            if(CommonHelper.NotTrackableTypes.Count > 0)
            {
            srcTable.AddColumn(new SourceColumn("abc1", CommonHelper.NotTrackableTypes[0], 1));
            }
            srcTable.AddColumn(new SourceColumn("abc2", "int", 2));

            srcTable.SetAllActivate(true);

            int active = 0;
            foreach (SourceColumn srcCol in srcTable.Columns.Values) if (srcCol.ActivateTracking) active++;
            Assert.AreEqual(1, active);
        }

        [TestMethod, ExpectedException(typeof(ArgumentException))]
        public void IsColumnOrphanArgNullTest()
        {
            srcTable.AddOrphantColumn(null);
        }

        [TestMethod, ExpectedException(typeof(ArgumentException))]
        public void IsColumnOrphanArgEmptyTest()
        {
            srcTable.AddOrphantColumn("");
        }

        [TestMethod]
        public void IsColumnOrphan1Test()
        {
            srcTable.AddOrphantColumn("abc");

            Assert.IsTrue(srcTable.HasOrphanTriggerColumn);
        }

        [TestMethod]
        public void IsColumnOrphan2Test()
        {
            srcTable.AddOrphantColumn("abc");

            Assert.IsTrue(srcTable.IsColumnOrphan("abc"));
        }

        [TestMethod]
        public void IsAnyToActivateNoTest()
        {
            Assert.IsFalse(srcTable.IsAnyToActivate());
        }

        [TestMethod]
        public void IsAnyToActivateYesTest()
        {
            SourceColumn sc = new SourceColumn("abc", "int", 1);
            sc.ActivateTracking = true;
            srcTable.AddColumn(sc);
            Assert.IsTrue(srcTable.IsAnyToActivate());
        }

        [TestMethod]
        public void IsDropTrackingRequestedNoTest()
        {
            SourceColumn sc = new SourceColumn("abc", "int", 1);
            sc.IsTracked = true;
            srcTable.AddColumn(sc);
            Assert.IsFalse(srcTable.IsDropTrackingRequested());
        }

        [TestMethod]
        public void IsDropTrackingRequestedYesTest()
        {
            SourceTable st = new SourceTable("abc","abc", true);
            SourceColumn sc = new SourceColumn("abc", "int", 1);
            sc.ActivateTracking = false;
            st.AddColumn(sc);
            Assert.IsTrue(st.IsDropTrackingRequested());
        }
    }
}

